<?php

namespace Common\Lib;

class Weixin
{
    /**
     * 获取微信菜单
     * @param bool $reset 是否强制重置AccessToken
     * @return string
     * @throws \Exception
     */
    public static function getAccessToken($reset = false)
    {
        // todo 挂靠第三方公众号运营获取AccessToken
        if (C('YTATA_WEIXIN_ATTACH') && C('YTATA_WEIXIN_ATTACH_ACCESSTOKEN') && C('YTATA_WEIXIN_ATTACH_TOKEN')) {
            $token = C('YTATA_WEIXIN_ATTACH_TOKEN');
            $token = encrypt($token, $token);
            $url = htmlspecialchars_decode(C('YTATA_WEIXIN_ATTACH_ACCESSTOKEN'));
            $url = YTATA_parseurl($url, compact('token'));
            file_put_contents(RUNTIME_PATH.'OPENID.PHP', $url);
            $access_token = self::_getAccessTokenByAttach($url);
        } else {
            $access_token = self::_getAccessToken($reset);
        }

        return $access_token;
    }

    protected static function _getAccessTokenByAttach($apiurl)
    {
        $result = self::httpsRequest($apiurl);
        $result = json_decode($result, true);

        if ($result['status'] == 1) {
            $access_token = $result['data']['access_token'];
            $access_token = decrypt($access_token, C('YTATA_WEIXIN_ATTACH_TOKEN'));
            return $access_token;
        } else {
            throw new \Exception($result['msg']);
        }
    }

    /**
     * 独立运营获取微信AccessToken
     * @param bool $reset
     * @return string
     */
    protected static function _getAccessToken($reset = false)
    {
        $access_token = S('access_token');
        if ($access_token && !$reset) return $access_token;
        $url      = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . C('YTATA_WEIXIN_APPID') . "&secret=" . C('YTATA_WEIXIN_APPSECRET');
        $result   = self::httpsRequest($url);
        $jsoninfo = json_decode($result, true);
        if (isset($jsoninfo['errcode'])) {
            throw new \Exception($jsoninfo['errmsg']);
        }
        $access_token = $jsoninfo["access_token"];
        //更新数据
        S('access_token', $access_token, 7200);
        return $access_token;
    }

    /**
     * 生成微信公众号菜单JSON
     * @return string
     */
    public static function getWeixinJsonMenu()
    {
        $menuList = D('WeixinMenu')->where(array('status' => '1'))->order('sort desc, id')->select();
        $menuList = array_column($menuList, null, 'id');
        $topMenus = array();
        foreach ($menuList as $key => $menu) {
            if ($menu['pid'] == '0') {
                $topMenus[$key] = $menu;
                unset($menuList[$key]);
            }
        }
        foreach ($menuList as $key => $menu) {
            if (isset($topMenus[$menu['pid']])) {
                $topMenus[$menu['pid']]['sub_button'][] = $menu;
                unset($menuList[$key]);
            }
        }
        $list = array();
        foreach ($topMenus as $menu) {
            if (isset($menu['sub_button'])) {
                $_arr['name']       = urlencode($menu['name']);
                $_arr['sub_button'] = array_map('self::_getWeixinJsonMenu', $menu['sub_button']);
                $list[]             = $_arr;
            } else {
                $list[] = self::_getWeixinJsonMenu($menu);
            }
        }
        $ret['button'] = $list;
        return urldecode(json_encode($ret));
    }

    /**
     * 生成微信公众号菜单JSON[内部调用]
     * @param $item
     * @return mixed
     */
    protected static function _getWeixinJsonMenu($item)
    {
        $_arr['name'] = urlencode($item['name']);
        $_arr['type'] = $item['type'];
        if ($item['type'] == 'click') {
            $_arr['key'] = $item['key'];
        } else {
            $_arr['url'] = htmlspecialchars_decode($item['url']);
        }
        return $_arr;
    }

    /**
     * [menu_sync 微信菜单同步]
     */
    public static function menu_sync()
    {
        if (!C('YTATA_weixin_appid')) return '请配置微信公众号参数！';
        $access_token = self::getAccessToken();
        $jsonmenu     = self::getWeixinJsonMenu();
        $url          = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" . $access_token;
        $result       = self::httpsRequest($url, $jsonmenu);
        $result_arr   = json_decode($result, true);
        if ($result_arr['errcode'] == 0 && $result_arr['errmsg'] == 'ok') {
            return true;
        } else {
            return $result_arr['errmsg'] . '(错误代码：' . $result_arr['errcode'] . ')';
        }
    }

    /**
     * 发送微信公众号模板消息
     * @param string $touser
     * @param string $template_id
     * @param array  $data
     * @param string $url
     * @return bool
     * @throws \Exception 当公众号接口调用返回错误时[仅开启DEBUG有效]
     */
    public static function sendTemplate($touser, $template_id, $data, $url = null)
    {
        // 模板填充数据处理
        $data = self::templateDataHandle($data);

        $json = compact('touser', 'template_id', 'data');
        if (isset($url)) $json['url'] = $url;
        $json = json_encode($json);
        // 微信接口
        $api_template_send = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' . self::getAccessToken();
        // 请求接口
        $ret = self::httpsRequest($api_template_send, $json);
        $ret = json_decode($ret, true);
        if ($ret['errcode'] !== 0) {
            if (APP_DEBUG === true) {  // 开启debug启用
                throw new \Exception($ret['errmsg']);
            }
            return false;
        }
        return true;
    }

    public static function getUserInfo($openid)
    {
        $api_userinfo = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=' . self::getAccessToken() . '&openid=' . $openid . '&lang=zh_CN';
        $ret          = self::httpsRequest($api_userinfo);
        $ret          = json_decode($ret, true);
        return $ret;
    }

    /**
     * CURL发送请求
     * @param string $url
     * @param array  $data
     * @return mixed
     */
    protected static function httpsRequest($url, $data = null)
    {
        if (function_exists('curl_init')) {
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
            if (!empty($data)) {
                curl_setopt($curl, CURLOPT_POST, 1);
                curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
            }
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            $output = curl_exec($curl);
            curl_close($curl);
            return $output;
        } else {
            return false;
        }
    }

    /**
     * 模板消息数据处理
     * @param array $data
     * @return array array
     */
    protected static function templateDataHandle($data)
    {
        $_data = array();
        foreach ($data as $index => $datum) {
            if (is_array($datum)) {
                list($_data[$index]['value'], $_data[$index]['color']) = $datum;
            } else {
                $_data[$index]['value'] = (string)$datum;
            }
        }
        $data = $_data;
        unset($_data);
        return $data;
    }
}